package ControlLayer;

import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import DBLayer.DBConnection;
import DBLayer.DBRBDate;
import DBLayer.IFDBRBDate;
import ModelLayer.RBDate;
import ModelLayer.RoomType;

public class RBDateCtr {
	private RoomCtr roomCtr;

	public RBDateCtr() {
		roomCtr = new RoomCtr();

	}

	public boolean isRoomsAvailableForRT(int rtId, int quantity,
			Date startDate, Date endDate) {
		boolean isAvailable = true;
		Calendar start = Calendar.getInstance();
		start.setTime(startDate);
		Calendar end = Calendar.getInstance();
		end.setTime(endDate);
		int maxNrOfRooms = roomCtr.getAvailableRoomsNrForRT(rtId);
		for (Date date = start.getTime(); !start.after(end); start.add(
				Calendar.DATE, 1)) {
			RBDate rbDate = getRBDate(rtId, date);
			if (rbDate != null) {
				if (rbDate.getNrOfAvailableRoom() - quantity < 0) {
					isAvailable = false;
					return isAvailable;
				}
			} else {
				if (maxNrOfRooms < quantity) {
					isAvailable = false;
					return isAvailable;
				}
			}
		}
		return isAvailable;
	}

	public RBDate getRBDate(int rtId, Date date) {
		IFDBRBDate dbDate = new DBRBDate();
		return dbDate.getDate(rtId, date, true);
	}

	public int insertRBDate(int rtId, Date date, int nr) {
		int rc = 0;
		RBDate rbDate = new RBDate();
		rbDate.setRoomType(new RoomType(rtId));
		rbDate.setDate(date);
		rbDate.setNrOfAvailableRoom(nr);
		try {
			DBConnection.startTransaction();
			IFDBRBDate dbRBDate = new DBRBDate();
			rc = dbRBDate.insertDate(rbDate);
			DBConnection.commitTransaction();
		} catch (Exception e) {
			DBConnection.rollbackTransaction();
		}
		return rc;
	}

	public int updateRBDate(int rtId, Date date, int nr) {
		int rc = 0;
		RBDate rbDate = new RBDate();
		rbDate.setRoomType(new RoomType(rtId));
		rbDate.setDate(date);
		rbDate.setNrOfAvailableRoom(nr);
		try {
			DBConnection.startTransaction();
			IFDBRBDate dbRBDate = new DBRBDate();
			rc = dbRBDate.updateDate(rbDate);
			DBConnection.commitTransaction();
		} catch (Exception e) {
			DBConnection.rollbackTransaction();
		}
		return rc;
	}

	public int deleteRBDate(int rtId, Date date) {
		int rc = -1;
		try {
			DBConnection.startTransaction();
			IFDBRBDate dbRBDate = new DBRBDate();
			rc = dbRBDate.deleteDate(rtId, date);
			DBConnection.commitTransaction();
		} catch (Exception e) {
			DBConnection.rollbackTransaction();
		}
		return rc;
	}

	// get last date of booking year for room type
	public Date getLastDateForRT(int rtId) {
		IFDBRBDate dbRBDate = new DBRBDate();
		return dbRBDate.getLastDate(rtId);
	}

	public LinkedList<RBDate> getAllRBdateForRT(int rtId) {
		IFDBRBDate dbRBDate = new DBRBDate();
		return dbRBDate.getDatesForRT(rtId, false);
	}

	public void incrementNrOfAvaiRoomForRT(int rtId, int quantity) {
		LinkedList<RBDate> rbdates = getAllRBdateForRT(rtId);
		for (RBDate date : rbdates) {
			date.setNrOfAvailableRoom(date.getNrOfAvailableRoom() + quantity);
			updateRBDate(rtId, date.getDate(), date.getNrOfAvailableRoom());
		}
	}

	public void decrementNrOfAvaiRoomForRT(int rtId, int quantity) {
		LinkedList<RBDate> rbdates = getAllRBdateForRT(rtId);
		for (RBDate date : rbdates) {
			date.setNrOfAvailableRoom(date.getNrOfAvailableRoom() - quantity);
			updateRBDate(rtId, date.getDate(), date.getNrOfAvailableRoom());
		}
	}

	// increase number of available room for one room type for 1
	public void incrementNrOfAvaiRoom(int rtId, Date startDate, Date endDate,
			int quantity) {

		Calendar start = Calendar.getInstance();
		start.setTime(startDate);
		Calendar end = Calendar.getInstance();
		end.setTime(endDate);
		for (Date date = start.getTime(); !start.after(end); start.add(
				Calendar.DATE, 1)) {
			RBDate rbDate = getRBDate(rtId, start.getTime());
			int numberOfRoom = rbDate.getNrOfAvailableRoom();
			rbDate.setNrOfAvailableRoom(numberOfRoom + quantity);
			updateRBDate(rbDate.getRoomType().getId(), rbDate.getDate(),
					rbDate.getNrOfAvailableRoom());

		}
	}

	// increase number of available room for one roomtype for 1
	public void decrementNrOfAvaiRoom(int rtId, Date startDate, Date endDate,
			int quantity) throws RoomBookingException {
		Calendar start = Calendar.getInstance();
		start.setTime(startDate);
		Calendar end = Calendar.getInstance();
		int numberOfRoom;
		end.setTime(endDate);
		for (Date date = start.getTime(); !start.after(end); start.add(
				Calendar.DATE, 1)) {
			RBDate rbDate = getRBDate(rtId, start.getTime());
			if (rbDate != null) {
				numberOfRoom = rbDate.getNrOfAvailableRoom();
			} else {
				// TODO
				int maxRoom = roomCtr.getAvailableRoomsNrForRT(rtId);
				insertRBDate(rtId, start.getTime(), maxRoom);
				numberOfRoom = maxRoom;
				rbDate = new RBDate();
				rbDate.setDate(start.getTime());
				rbDate.setRoomType(new RoomType(rtId));
			}
			if (numberOfRoom - quantity < 0)
				throw new RoomBookingException("Not enough rooms for booking");
			rbDate.setNrOfAvailableRoom(numberOfRoom - quantity);
			updateRBDate(rbDate.getRoomType().getId(), rbDate.getDate(),
					rbDate.getNrOfAvailableRoom());
		}
	}

	public LinkedList<RBDate> getAllRBDateForMonth(int rtId, Date startDate) {
		LinkedList<RBDate> dates = new LinkedList<RBDate>();
		Calendar start = Calendar.getInstance();
		start.setTime(startDate);
		int daysOfMonth = start.getActualMaximum(Calendar.DAY_OF_MONTH);
		for (int i = 0; i < daysOfMonth; i++) {
			IFDBRBDate dbRBDate = new DBRBDate();
			RBDate date = dbRBDate.getDate(rtId, start.getTime(), false);
			dates.add(date);
			start.add(Calendar.DATE, 1);
		}
		return dates;
	}

	public void insertRBDateForYear(int rtId, int year) {
		int nrOfAvaiRoom = roomCtr.getAvailableRoomsNrForRT(rtId);

		Calendar calendarStart = Calendar.getInstance();
		calendarStart.set(Calendar.YEAR, year);
		calendarStart.set(Calendar.MONTH, 0);
		calendarStart.set(Calendar.DAY_OF_MONTH, 1);

		Calendar calendarEnd = Calendar.getInstance();
		calendarEnd.set(Calendar.YEAR, year);
		calendarEnd.set(Calendar.MONTH, 11);
		calendarEnd.set(Calendar.DAY_OF_MONTH, 31);

		while (!calendarStart.after(calendarEnd)) {
			Date date = calendarStart.getTime();
			insertRBDate(rtId, date, nrOfAvaiRoom);
			calendarStart.add(Calendar.DATE, 1);
		}
	}
}
